package com.mango.iot.gateway.tcp.handler.event;

import com.mango.iot.gateway.tcp.handler.Process;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import com.mango.iot.gateway.tcp.constants.ProtocolConstants;
import com.mango.iot.gateway.tcp.message.GpsMessage;
import com.mango.iot.gateway.tcp.utils.ByteUtils;
import com.mango.iot.gateway.tcp.utils.CommUtils;
import com.mango.iot.gateway.tcp.utils.NetUtils;

/**
 * GPS定位包处理 0x22
 *
 * @author liangfeihu
 * @number 53669
 * @since 2021/4/7 上午9:35
 */
@Slf4j
public class GpsLocation implements Process {

    @Override
    public void execute(GpsMessage msg) throws Exception {
        byte[] packetContent = msg.getPacketContent();
        // 处理年月日
        String dateTime = CommUtils.handleDateTime(packetContent);
        log.info("[GpsLocation]dateTime={}", dateTime);
        // 处理卫星数、经纬度、速度
        handleLongitudeAndLatitude(packetContent);
        // 处理航行、状态
        String sail = handleSailState(packetContent);
        log.info("[GpsLocation]sail={}", sail);
        // 处理MCC、MNC、LAC、Cell ID
        handleMccAndCell(packetContent);
        // 处理ACC、gpsUpDataType
        handleGpsUpDataType(packetContent);
        // 0x2D 定位包需要回复
        if (ProtocolConstants.PROTOCOL_GPS_LOCATION_REPLY == msg.getProtocolNo()) {
            sedReplyMsg(msg);
        }
    }

    private void handleGpsUpDataType(byte[] packetContent) {
        byte acc = packetContent[26];
        String accStr = "";
        if (0x00 == acc) {
            accStr = "ACC 低";
        } else if (0x01 == acc) {
            accStr = "ACC 高";
        } else {
            accStr = "ACC 未知";
        }
        byte upMode = packetContent[27];
        String gpsUpDataType = getGpsUpDataType(upMode);

        byte gpsMode = packetContent[28];
        String gpsStr = "";
        if (0x00 == gpsMode) {
            gpsStr = "GPS 实时上传";
        } else if (0x01 == gpsMode) {
            gpsStr = "GPS 补传";
        } else {
            gpsStr = "GPS 未知";
        }

        log.info("[GpsLocation]acc={} gpsUpType={} gpsMode={}", accStr, gpsUpDataType, gpsStr);
    }

    private void handleMccAndCell(byte[] packetContent) {
        byte[] mcc = new byte[]{packetContent[18], packetContent[19]};
        int mccNum = ByteUtils.byteArrayToInt(mcc, true);
        int mncNum = 0xFF & packetContent[20];
        byte[] lac = new byte[]{packetContent[21], packetContent[22]};
        int lacNum = ByteUtils.byteArrayToInt(lac, true);
        byte[] cell = new byte[]{0x00, packetContent[23], packetContent[24], packetContent[25]};
        int cellId = ByteUtils.byteArrayToInt(cell);
        log.info("[GpsLocation]mccNum:{} mncNum:{} lacNum:{} cellId:{}", mccNum, mncNum, lacNum, cellId);
    }

    private void handleLongitudeAndLatitude(byte[] packetContent) {
        int gpsNum = 0x0F & packetContent[6];
        int gpsLength = 0x0F & (packetContent[6] >> 4);
        // longitude and latitude
        byte[] lat = new byte[]{packetContent[7], packetContent[8], packetContent[9], packetContent[10]};
        double latitude = ByteUtils.byteArrayToInt(lat) / 1800000d;
        byte[] lon = new byte[]{packetContent[11], packetContent[12], packetContent[13], packetContent[14]};
        double longitude = ByteUtils.byteArrayToInt(lon) / 1800000d;
        int speed = 0xFF & packetContent[15];
        log.info("[GpsLocation]gpsNum:{} gpsLength:{} longitude:{} latitude:{} speed:{}",
                gpsNum, gpsLength, longitude, latitude, speed);
    }

    private String handleSailState(byte[] packetContent) {
        byte[] sail = new byte[]{packetContent[16], packetContent[17]};
        StringBuilder builder = new StringBuilder();
        int one = 0x00000001 & (sail[0] >> 4);
        builder.append(one == 1 ? "GPS 已定位" : "GPS 未定位").append(", ");
        int two = 0x00000001 & (sail[0] >> 5);
        builder.append(two == 0 ? "实时GPS" : "差分定位").append("、");
        int three = 0x00000001 & (sail[0] >> 2);
        builder.append(three == 1 ? "北纬" : "南纬").append("、");
        int four = 0x00000001 & (sail[0] >> 3);
        builder.append(four == 1 ? "西经" : "东经").append("、");

        byte[] intArr = new byte[4];
        intArr[0] = 0x00;
        intArr[1] = 0x00;
        intArr[2] = (byte) (0x03 & sail[0]);
        intArr[3] = sail[1];
        int sailState = ByteUtils.byteArrayToInt(intArr);
        builder.append("航向").append(sailState).append("° 。");
        return builder.toString();
    }

    private void sedReplyMsg(GpsMessage msg) {
        // 构造GPS定位响应包
        byte[] replyPacket = NetUtils.buildCommonReplyPacket(msg);
        ChannelHandlerContext ctx = msg.getCtx();
        if (ctx.channel().isWritable()) {
            // 将GPS定位响应包发送出去
            ctx.pipeline().writeAndFlush(Unpooled.wrappedBuffer(replyPacket));
        } else {
            ctx.pipeline().close();
        }
    }

    private String getGpsUpDataType(byte upMode) {
        if (0x00 == upMode) {
            return "定时上报";
        } else if (0x01 == upMode) {
            return "定距上报";
        } else if (0x02 == upMode) {
            return "拐点上报";
        } else if (0x03 == upMode) {
            return "ACC状态改变上传";
        } else if (0x04 == upMode) {
            return "静止最后位置上传";
        } else if (0x05 == upMode) {
            return "上电登录成功后直接上传";
        }
        return "";
    }

}
